/*
  author Sylvain Bertrand <sylvain.bertrand@gmail.com>
  Protected by linux GNU GPLv2
  Copyright 2012-2014
*/
#include <linux/pci.h>
#include <linux/cdev.h>
#include <asm/unaligned.h>

#include <alga/rng_mng.h>
#include <uapi/alga/pixel_fmts.h>
#include <alga/timing.h>
#include <alga/amd/atombios/atb.h>
#include <uapi/alga/amd/dce6/dce6.h>
#include <alga/amd/atombios/vm.h>
#include <alga/amd/atombios/cm.h>
#include <alga/amd/atombios/pp.h>
#include <alga/amd/atombios/vram_info.h>

#include "../mc.h"
#include "../rlc.h"
#include "../ih.h"
#include "../fence.h"
#include "../ring.h"
#include "../dmas.h"
#include "../ba.h"
#include "../cps.h"
#include "../gpu.h"
#include "../drv.h"

#include "../regs.h"

#include "../smc_tbls.h"

#include "ctx.h"
#include "private.h"

#ifdef CONFIG_ALGA_AMD_SI_DYN_PM_LOG
#define L(fmt,...) printk(KERN_INFO fmt "\n", ##__VA_ARGS__)
void smc_eng_clk_dump(struct smc_eng_clk *tbl)
{
	u32 tmp;

	L("SMC_ENG_CLK START");

	tmp = get_unaligned_be32(&tbl->cg_eng_pll_func_ctl_0);
	L("cg_eng_pll_func_ctl_0=0x%08x",tmp);

	tmp = get_unaligned_be32(&tbl->cg_eng_pll_func_ctl_1);
	L("cg_eng_pll_func_ctl_1=0x%08x",tmp);
	
	tmp = get_unaligned_be32(&tbl->cg_eng_pll_func_ctl_2);
	L("cg_eng_pll_func_ctl_2=0x%08x",tmp);

	tmp = get_unaligned_be32(&tbl->cg_eng_pll_func_ctl_3);
	L("cg_eng_pll_func_ctl_3=0x%08x",tmp);

	tmp = get_unaligned_be32(&tbl->cg_eng_pll_ss_0);
	L("cg_eng_pll_ss_0=0x%08x",tmp);

	tmp = get_unaligned_be32(&tbl->cg_eng_pll_ss_1);
	L("cg_eng_pll_ss_1=0x%08x",tmp);

	tmp = get_unaligned_be32(&tbl->clk);
	L("clk=0x%08x",tmp);

	L("SMC_ENG_CLK END");
}
#endif

long smc_eng_clk_from_atb_pp(struct ctx *ctx, struct atb_pp_lvl *atb_lvl,
							struct smc_lvl *smc_lvl)
{
	struct smc_eng_clk *smc_eng_clk;
	struct eng_pll eng_pll;
	long r;

	r = eng_pll_compute(ctx, atb_lvl->eng_clk, &eng_pll);
	if (r == -SI_ERR)
		return -SI_ERR;

	/*--------------------------------------------------------------------*/
	smc_eng_clk = &smc_lvl->eng_clk;

	put_unaligned_be32(eng_pll.cg_eng_pll_func_ctl_0,
					&smc_eng_clk->cg_eng_pll_func_ctl_0);
	put_unaligned_be32(eng_pll.cg_eng_pll_func_ctl_1,
					&smc_eng_clk->cg_eng_pll_func_ctl_1);
	put_unaligned_be32(eng_pll.cg_eng_pll_func_ctl_2,
					&smc_eng_clk->cg_eng_pll_func_ctl_2);
	put_unaligned_be32(eng_pll.cg_eng_pll_func_ctl_3,
					&smc_eng_clk->cg_eng_pll_func_ctl_3);

	put_unaligned_be32(eng_pll.cg_eng_pll_ss_0,
						&smc_eng_clk->cg_eng_pll_ss_0);
	put_unaligned_be32(eng_pll.cg_eng_pll_ss_1,
						&smc_eng_clk->cg_eng_pll_ss_1);
	
	put_unaligned_be32(atb_lvl->eng_clk, &smc_eng_clk->clk);
	/*--------------------------------------------------------------------*/
	return 0;
}
